/**
 * Copyright (c) 2011 Daniel Centore
 *
 * ex: set filetype=java expandtab tabstop=4 shiftwidth=4 :
 * 
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation.
 */
package wiiWired.controller.console;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import wiiWired.controller.console.wizard.MoteConnectionManager;
import wiiWired.controller.data.RaceModel;
import wiiWired.controller.mote.ControllerModel;
import wiiWired.controller.mote.MoteController;
import wiiWired.controller.mote.TimerController;

/**
 * Class for handling the main window
 * 
 * @author Daniel Centore
 * 
 */
public class JBWindow
{
	private static int oneRowHeight;
	private static int lastHeight; // the last number of rows in the model

	private static JFrame frame; // the jframe
	private static JTable table; // table of stuff
	private static JButton start; // temporary start button

	private static RaceTableModel model; // race data model

	/**
	 * Initializes the window and shows it
	 */
	public static void initialize()
	{
		new JBWindow();

		new Thread()
		{
			public void run()
			{
				while (true)
				{
					JBWindow.fireUpdateRequired();

					try
					{
						Thread.sleep(1);
					} catch (InterruptedException e)
					{
					}
				}
			}
		}.start();
	}

	private JBWindow()
	{
		frame = new JFrame("WiiWired Timing System");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		start = new JButton("Start");
		JButton stop = new JButton("Stop");

		stop.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				for (MoteController m : ControllerModel.getModel())
					m.setTiming(false);

				TimerController.setTiming(false);
			}
		});

		final RaceModel raceModel = new RaceModel();

		start.addMouseListener(new MouseListener()
		{
			@Override
			public void mouseClicked(MouseEvent arg0)
			{
			}

			@Override
			public void mouseEntered(MouseEvent arg0)
			{
			}

			@Override
			public void mouseExited(MouseEvent arg0)
			{
			}

			@Override
			public void mouseReleased(MouseEvent arg0)
			{
			}

			@Override
			public void mousePressed(MouseEvent arg0) // so we get it on pressed event, not released.
			{
				TimerController.sendStartSignal(raceModel);
			}
		});

		JButton connection = new JButton("Mote Connection Manager");
		connection.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				new MoteConnectionManager(JBWindow.this.frame);
			}
		});

		table = new JTable(model = new RaceTableModel(raceModel));
		oneRowHeight = table.getRowHeight();

		table.setDefaultRenderer(String.class, new MultiLineCellRenderer());

		table.getTableHeader().setReorderingAllowed(false); // throws errors.

		JPanel bottom = new JPanel();

		frame.add(new JScrollPane(table), BorderLayout.CENTER);
		frame.add(bottom, BorderLayout.SOUTH);

		bottom.add(start);
		bottom.add(stop);
		bottom.add(connection);

		frame.pack();
		frame.setVisible(true);
	}

	public void setRowHeight(int row, int height)
	{
		table.setRowHeight(row, oneRowHeight * height); // 16 is default height
	}

	/**
	 * Reorders the columns, then updates table
	 */
	public static void fireUpdateRequired()
	{
		ControllerModel.sortMotes();

		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				int[] heights = new int[table.getRowCount()]; // this stuff prevents the ugly flicker

				for (int i = 0; i < heights.length; i++)
					heights[i] = table.getRowHeight(i);

				model.fireTableStructureChanged();

				if (lastHeight == heights.length)
				{
					for (int i = 0; i < heights.length; i++)
						if (heights[i] > 0) // legal heights only
							table.setRowHeight(i, heights[i]);
				}
				else
				{
					for (int i = 0; i < heights.length; i++)
						table.setRowHeight(i, oneRowHeight);
				}

				setHeaderColors();

				lastHeight = heights.length;
			}
		});
	}

	private static void setHeaderColors() // helper
	{
		MoteController[] model = ControllerModel.getModel();

		for (int i = 0; i < model.length; i++)
		{
			int start = i * 2;
			start++;

			setColumnColor(start, model[i].getColor());
			if (model[i].hasNunchuk())
				setColumnColor(start + 1, model[i].getColor());
		}
	}

	private static void setColumnColor(int column, Color c) // helper
	{
		DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
		JTableHeader jth = table.getTableHeader();
		TableColumnModel tcm = jth.getColumnModel();
		TableColumn tb = tcm.getColumn(column);
		tb.setHeaderRenderer(renderer);
		renderer.setBackground(c);
	}
	
	// Based on http://www.codeguru.com/java/articles/131.shtml
	class MultiLineCellRenderer extends JTextArea implements TableCellRenderer
	{
		private static final long serialVersionUID = 1L;

		public MultiLineCellRenderer()
		{
			setLineWrap(true);
			setWrapStyleWord(true);
			setOpaque(true);
		}

		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
		{
			String val = value.toString();

			int h = JBWindow.oneRowHeight * (val.split("\n").length);
			if (table.getRowHeight() != h) // needed so we dont murder our cpu
				table.setRowHeight(row, Math.max(h, table.getRowHeight(row)));

			if (isSelected)
			{
				setForeground(table.getSelectionForeground());
				setBackground(table.getSelectionBackground());
			}
			else
			{
				setForeground(table.getForeground());
				setBackground(table.getBackground());
			}
			setFont(table.getFont());
			if (hasFocus)
			{
				setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
				if (table.isCellEditable(row, column))
				{
					setForeground(UIManager.getColor("Table.focusCellForeground"));
					setBackground(UIManager.getColor("Table.focusCellBackground"));
				}
			}
			else
			{
				setBorder(new EmptyBorder(1, 2, 1, 2));
			}
			setText((value == null) ? "" : value.toString());
			return this;
		}
	}

}

